package everydaydo;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.BevelBorder;

@SuppressWarnings("serial")
public class Sudoku extends JFrame implements ActionListener {

	private final int[][] m_Matrix = new int[9][9];
	private JButton button;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		try {
			Sudoku dialog = new Sudoku();
			dialog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			dialog.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Create the dialog.
	 */
	public Sudoku() {
		setTitle("\u6570\u72EC\u6C42\u89E3");
		setBounds(100, 100, 578, 374);
		getContentPane().setLayout(null);
		{
			JPanel buttonPane = new JPanel();
			buttonPane.setBounds(0, 303, 559, 33);
			buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
			getContentPane().add(buttonPane);
			{
				{
					button = new JButton(
							"\u6253\u5F00\u6587\u4EF6\u5E76\u6F14\u7B97");
					button.addActionListener(this);
					buttonPane.add(button);
				}
			}
		}
		{
			JPanel panel = new JPanel();
			panel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null,
					null, null));
			panel.setBounds(10, 10, 354, 270);
			getContentPane().add(panel);
			panel.setLayout(new GridLayout(9, 9, 1, 1));
			for (int i = 0; i < 81; i++) {
				JTextField field = new JTextField();
				field.setText("0");
				panel.add(field);
			}

		}
	}

	private void Fill(int[][] currentMatrix, int startIndex) {// 填充矩阵的递归算法

		@SuppressWarnings("unused")
		int start_i = startIndex / 9;// 起点行索引
		@SuppressWarnings("unused")
		int start_j = startIndex % 9;// 起点列索引

		int next_Index;// 待插入数字的索引
		int next_i = 9, next_j = 9;// 待插入的位置

		for (next_Index = startIndex; next_Index <= 80; next_Index++) {// 得到要插入数字的位置
			if (currentMatrix[next_Index / 9][next_Index % 9] == 0) {// 0表示未填写，可插入数字
				next_i = next_Index / 9;
				next_j = next_Index % 9;
				break;
			}
		}
		if (next_Index > 80) {// 若找不到可插入的位置，说明计算结束
			for (int i = 0; i < 9; i++) {// 显示矩阵
				for (int j = 0; j < 9; j++) {
					System.out.print(currentMatrix[i][j] + " ");
				}
				System.out.println();
			}
			this.matrixToTable();
			return;

		}
		for (int num = 1; num <= 9; num++) {
			if (this.check(currentMatrix, next_i, next_j, num)) {// 如果此位置可插入数字
				currentMatrix[next_i][next_j] = num;
				Fill(currentMatrix, next_Index + 1);
				currentMatrix[next_i][next_j] = 0;

			} else {

			}

		}

	}

	private boolean check(int[][] Matrix, int current_i, int current_j, int num) {// 检查(i,j)位的num在矩阵m中是否合法
		for (int i = 0; i < 9; i++) {// 第一步检查所在行
			if (Matrix[i][current_j] == num) {
				// System.out.println(num + "与" + i + "," + current_j +
				// "的元素重复");
				return false;
			}
		}
		for (int j = 0; j < 9; j++) {// 第二步检查所在列
			if (Matrix[current_i][j] == num) {
				// System.out.println(num + "与" + current_i + "," + j +
				// "的元素重复");
				return false;
			}
		}

		// 第三步是检查所在的小方形。思路是先找出位置所在方形的中心点，然后获取包括中心的9个元素，再检查重复
		// 所以要建立一个012->1，345->4，678->7的映射，这个可以单独写一个getCenter来完成
		int center_i = getCenter(current_i);
		int center_j = getCenter(current_j);

		int[] sub_array = new int[9];// subarray是存放小方形数字的数组;
		sub_array[0] = Matrix[center_i - 1][center_j - 1];
		sub_array[1] = Matrix[center_i][center_j - 1];
		sub_array[2] = Matrix[center_i + 1][center_j - 1];
		sub_array[3] = Matrix[center_i - 1][center_j];
		sub_array[4] = Matrix[center_i][center_j];
		sub_array[5] = Matrix[center_i + 1][center_j];
		sub_array[6] = Matrix[center_i - 1][center_j + 1];
		sub_array[7] = Matrix[center_i][center_j + 1];
		sub_array[8] = Matrix[center_i + 1][center_j + 1];
		for (int i = 0; i < 9; i++) {// 搜索所在小区域有没重复数字
			if (sub_array[i] == num) {
				// System.out.println(num + "与位于(" + center_i + "," + center_j
				// + ")为中心的第" + i + "元素重复");
				return false;
			}
		}

		return true;
	}

	private int getCenter(int n) {
		if (n >= 0 && n <= 2)
			return 1;
		if (n >= 3 && n <= 5)
			return 4;
		if (n >= 6 && n <= 8)
			return 7;
		return -1;

	}

	@SuppressWarnings("unused")
	private void tableToMatrix() {
		JPanel numberPanel = (JPanel) (this.getContentPane().getComponent(1));
		int count = numberPanel.getComponentCount();
		for (int i = 0; i < count; i++) {
			this.m_Matrix[i / 9][i % 9] = Integer
					.valueOf(((JTextField) (numberPanel.getComponent(i)))
							.getText());
		}

		// for (int i = 0; i < 9; i++) {
		// for (int j = 0; j < 9; j++) {
		// System.out.print(m_Matrix[i][j] + " ");
		// }
		// System.out.println();
		// }

	}

	private void matrixToTable() {
		JPanel numberPanel = (JPanel) (this.getContentPane().getComponent(1));
		@SuppressWarnings("unused")
		int count = numberPanel.getComponentCount();
		for (int i = 0; i < 9; i++) {
			for (int j = 0; j < 9; j++) {
				JTextField field = (JTextField) (numberPanel.getComponent(i * 9
						+ j));
				field.setText(String.valueOf(this.m_Matrix[i][j]));
			}
		}
	}

	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == button) {
			do_button_actionPerformed(arg0);
		}
	}

	protected void do_button_actionPerformed(ActionEvent arg0) {
		JFileChooser chooser = new JFileChooser();
		chooser.showOpenDialog(this);
		File file = chooser.getSelectedFile();
		if(file==null){
		   return;
		}
		FileReader reader;// 读入矩阵;
		BufferedReader bufferedReader;
		try {
			reader = new FileReader(file);// 读入矩阵
			bufferedReader = new BufferedReader(reader);
			for (int i = 0; i < 9; i++) {
				String str = bufferedReader.readLine();
				for (int j = 0; j < str.length(); j++) {
					m_Matrix[i][j] = Integer.valueOf(str.substring(j, j + 1));
				}
			}
			for (int i = 0; i < 9; i++) {// 显示矩阵
				for (int j = 0; j < 9; j++) {
					System.out.print(m_Matrix[i][j] + " ");
				}
				System.out.println();
			}
			System.out.println("以上为输入阵");
			this.Fill(m_Matrix, 0);
			reader.close();
			bufferedReader.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
